import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {DetectState, DetectStateModel} from '../../state/detect.state';
import {Select, Store} from '@ngxs/store';
import {ApiPage, DetectHistory, HttpResult, Kms, VideoFrame} from '../../core/http-entity';
import {RecognizeState, RecognizeStateModel} from '../../state/recognize.state';
import {ActivatedRoute, Router} from '@angular/router';
import {HttpClient, HttpParams} from '@angular/common/http';
import {environment} from '../../../environments/environment';
import {NzMessageService} from 'ng-zorro-antd';
import {VideoState, VideoStateModel} from '../../state/video.state';
import {VideoAction} from '../../state/video.action';


@Component({
  templateUrl: './detect.component.html',
  styleUrls: ['./detect.component.less']
})
export class DetectComponent implements OnInit, OnDestroy {

  @Select(DetectState)
  detect$: Observable<DetectStateModel>;
  detectSubscription: Subscription;


  @Select(RecognizeState)
  recognize$: Observable<RecognizeStateModel>;
  recognizeSubscription: Subscription;

  @Select(VideoState)
  video$: Observable<VideoStateModel>;
  videoSubscription: Subscription;

  video: File;

  detectHistory: DetectHistory[] = [];


  pageIndex = 0; // 从0开始计数
  total = 0;

  currentDetectResult: DetectHistory = new DetectHistory();

  selectedTarget: { ossKey: string, category: string, similarity: string };

  selectedTargetPolygon: {
    x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number,
    category: string, categoryCn: string, similarity: number
  };

  // 20201012
  kmsUrl: string;
  kmsResult: Kms[] = [];
  kms: Kms[] = [];
  similarity: number = 0;
  baiKeUrl: string;

  /*截取的目标*/
  @ViewChild('targetImg')
  targetImgElmRef: ElementRef;

  /*目标区域*/
  @ViewChild('clipTargetContainer')
  clipTargetContainerElmRef: ElementRef;

  targetsImageBase64 = [];

  @ViewChild('markedImage')
  markedImageElmRef: ElementRef;

  @ViewChild('videoFrameCanvas')
  videoFrameCanvasElmRef: ElementRef;

  detectingInterval: any;
  detectingSceneType = 0;

  similarTargets = [];

  constructor(private router: Router, private http: HttpClient, private nzMessage: NzMessageService,
              private route: ActivatedRoute, private store: Store) {

  }

  ngOnInit(): void {
    const startTime = new Date().getTime();
    this.detectingInterval = setInterval(() => {
      // 重复循环显示loading的
      if (this.detectingSceneType >= 3) {
        this.detectingSceneType = 0;
      } else {
        this.detectingSceneType++;
      }
      this.currentDetectResult.sceneType = this.detectingSceneType + '';

      if (new Date().getTime() - startTime > 60000) {
        // 超过1分钟就不loading了
        clearInterval(this.detectingInterval)
      }

    }, 200);

    this.route.paramMap.subscribe((paramMap) => {
      if (paramMap.has('detectId')) {
        // 图片的解析
        const detectId = paramMap.get('detectId');
        this.loadDetectHistory(detectId);
      } else {
        // 视频的解析
      }

    });


    /*
    不再使用下面的方式，而采用上面路由传参数的方式
    this.detectSubscription = this.detect$.subscribe((detectStateModel) => {
      if (detectStateModel.detectHistory.length == 0) {
        this.router.navigate(['/home']);
      } else {

        // 需要这样循环下，不然detectStateModel里的detectHistory是个只读属性的值，后面不好搞
        const data = [];
        detectStateModel.detectHistory.forEach(dh => data.push(dh));

        this.detectHistory = data;
        this.total = data.length;
        this.currentDetectResult = this.detectHistory[0];
      }
    });*/

    this.videoSubscription = this.video$.subscribe((videoStateModel) => {
      if (videoStateModel.video != null) {
        this.video = videoStateModel.video;
      }

    });

    this.recognizeSubscription = this.recognize$.subscribe((recognizeStateModel) => {
      if (recognizeStateModel == null || recognizeStateModel.recognizeJson == null) {
        return;
      }
      const recognizeData = JSON.parse(recognizeStateModel.recognizeJson) as DetectHistory;
      for (let i = 0, len = this.detectHistory.length; i < len; i++) {
        if (recognizeData.id === this.detectHistory[i].id) {
          this.detectHistory[i] = recognizeData;
          break;
        }
      }

      if (this.currentDetectResult && this.currentDetectResult.id === recognizeData.id) {
        this.currentDetectResult = recognizeData;
        // this.selectedTarget = recognizeData.piecesOssKey[0];

        // const targetJson = this.currentDetectResult.targetJson;
        // this.drawTargetsPolygon(targetJson);
        //
        // if (targetJson.length > 0) {
        //   this.selectedTargetPolygon = targetJson[0];
        // }
        // setTimeout(() => {
        // 这里就是处理的事件
        this.showDetectResult();
        // }, 2000);
      }
    });
  }

  ngOnDestroy(): void {
    this.store.dispatch(new VideoAction(null));
    // 改用了路由传参数，这个就不再需要了 this.detectSubscription.unsubscribe();
    this.recognizeSubscription.unsubscribe();
    this.videoSubscription.unsubscribe();


  }

  loadDetectHistory(detectId: string): void {
    const params = new HttpParams()
      .append('pageIndex', '1')
      .append('pageSize', '500')
      .append('detectId', detectId);
    this.http.get(`${environment.API_URL}/v1/detect-history`, {
      params
    }).subscribe((result: HttpResult<ApiPage<DetectHistory>>) => {
      if (HttpResult.succeed(result.code)) {
        this.detectHistory = result.data.records;
        this.total = result.data.total;
        if (this.total > 0) {
          this.currentDetectResult = this.detectHistory[0];

          this.showDetectResult();

          // this.drawMarkedLines(this.currentDetectResult);
          // // this.selectedTarget = this.currentDetectResult.piecesOssKey[0];
          //
          // const targetJson = this.currentDetectResult.targetJson;
          // this.drawTargetsPolygon(targetJson);
          //
          // if (targetJson.length > 0) {
          //   this.selectedTargetPolygon = targetJson[0];
          // }

        }
      }
    });
  }


  prevImage(): void {
    if (this.pageIndex > 0) {
      this.pageIndex--;
      this.currentDetectResult = this.detectHistory[this.pageIndex];

      this.showDetectResult();
    }
  }

  nextImage(): void {
    if (this.pageIndex < this.total - 1) {
      this.pageIndex++;
      this.currentDetectResult = this.detectHistory[this.pageIndex];
      this.showDetectResult();
    }
  }

  showDetectResult(): void {
    clearInterval(this.detectingInterval);

    this.drawMarkedLines(this.currentDetectResult);
    // this.selectedTarget = this.currentDetectResult.piecesOssKey[0];
    // this.selectedTargetPolygon = this.currentDetectResult.targetJson[0];
    if (this.currentDetectResult.targetJson) {
      this.selectTargetPolygon(this.currentDetectResult.targetJson[0]);
      this.drawTargetsPolygon(this.currentDetectResult.targetJson);
      this.baiKeUrl = this.currentDetectResult.baiKeUrl;
      console.log('第二个' + this.baiKeUrl);
    }
  }

  selectTarget(selectedTarget: { ossKey: string, category: string, similarity: string }): void {
    this.selectedTarget = selectedTarget;
  }

  selectTargetPolygon(targetPolygon: {
    x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number,
    category: string, categoryCn: string, similarity: number
  }): void {
    this.selectedTargetPolygon = targetPolygon;
    if (this.selectedTargetPolygon) {
      console.log('百分比', targetPolygon.similarity);
      console.log('卧槽', this.currentDetectResult);
      this.similarity = Math.round(this.selectedTargetPolygon.similarity * 100.00);
      this.baiKeUrl = this.currentDetectResult.baiKeUrl;
      console.log('第一个' + this.baiKeUrl);
    }
    // 查询相似图片
    if (this.selectedTargetPolygon) {
      // 去后台查询相似图片
      console.log('this.selectedTargetPolygon = ', this.selectedTargetPolygon);
      this.http.get(`${environment.API_URL}/v1/sample-oss-file/getByTypeName`, {
        params: {
          typeName: this.selectedTargetPolygon.categoryCn
        }
      }).subscribe((result: HttpResult<any>) => {
        if (HttpResult.succeed(result.code)) {
          if (result.data.length > 0) {
            if (result.data.length > 5) {
              this.similarTargets = result.data.slice(0, 5);
            } else {

              this.similarTargets = result.data;
            }
          }
        }
      });
      // 查询kms
      if (!(this.selectedTargetPolygon.categoryCn === '未识别')) {
        // this.kmsSearch(this.currentDetectResult.id + '', this.selectedTargetPolygon.categoryCn);
      }
    }
  }

  mismatch(): void {
    this.http.patch(`${environment.API_URL}/v1/detect-history/${this.currentDetectResult.id}/mismatched`, {}).subscribe(() => {
      this.nzMessage.success('反馈成功');
    });
  }

  drawMarkedLines(detectHistory: DetectHistory): void {
    if (detectHistory.status !== 3) {
      // 只有识别成功的状态才划线
      return;
    }

    const img = new Image();
    img.onload = () => {
      const testcanvasElm = document.createElement('canvas');
      testcanvasElm.width = detectHistory.originWidth;
      testcanvasElm.height = detectHistory.originHeight;
      /*新建一个画笔 并且开始画画*/
      const ctx = testcanvasElm.getContext('2d');
      ctx.drawImage(img, 0, 0);
      // ctx.fillStyle = 'transparent';
      ctx.strokeStyle = '#f00';

      detectHistory.targetJson.forEach(targetPolygon => {

        ctx.beginPath();
        ctx.moveTo(targetPolygon.x1, targetPolygon.y1);
        ctx.lineTo(targetPolygon.x2, targetPolygon.y2);
        ctx.lineTo(targetPolygon.x3, targetPolygon.y3);
        ctx.lineTo(targetPolygon.x4, targetPolygon.y4);

        ctx.closePath();
        ctx.stroke();
        // ctx.fill();

      });


      const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase();
      const dataURL = testcanvasElm.toDataURL('image/' + ext);
      setTimeout(() => {
        // 这里就是处理的事件
        this.markedImageElmRef.nativeElement.src = dataURL;
        // this.showDetectResult();
      }, 1000);
    };

    img.crossOrigin = 'anonymous';
    img.src = `${localStorage.getItem("targetRecognizePath")}/${detectHistory.ossKey}`;
  }

  drawTargetsPolygon(targetJson: Array<{
    x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number,
    category: string, similarity: number
  }>): void {
    this.targetsImageBase64 = [];
    // 不能用这个循环还画切图，因为画切图里都逻辑是异步都，会导致数组不一致
    // for (let i = 0, len = targetJson.length; i < len; i++) {
    //   this.appendClipTargetImage(targetJson[i], `${environment.OSS_URL}/${this.currentDetectResult.ossKey}`);
    // }

    // 画第一个目标
    this.appendClipTargetImage(targetJson, `${localStorage.getItem("targetRecognizePath")}/${this.currentDetectResult.ossKey}`, 0);
  }

  appendClipTargetImage(targetJson: Array<{
                          x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, x4: number, y4: number,
                          category: string, similarity: number
                        }>,
                        imgPath: string,
                        targetIdx: number): void {
    if (targetIdx >= targetJson.length) {
      // 所有目标都画完了
      return;
    }
    const targetPolygon = targetJson[targetIdx];
    /* 计算获得最大的X Y*/
    const minX = Math.min(targetPolygon.x1, targetPolygon.x2, targetPolygon.x3, targetPolygon.x4);
    const maxX = Math.max(targetPolygon.x1, targetPolygon.x2, targetPolygon.x3, targetPolygon.x4);
    const minY = Math.min(targetPolygon.y1, targetPolygon.y2, targetPolygon.y3, targetPolygon.y4);
    const maxY = Math.max(targetPolygon.y1, targetPolygon.y2, targetPolygon.y3, targetPolygon.y4);

    const clipWidth = maxX - minX;
    const clipHeight = maxY - minY;
    /*初始化图片*/
    const img = new Image();
    img.onload = () => {
      const testcanvasElm = document.createElement('canvas');
      testcanvasElm.width = clipWidth;
      testcanvasElm.height = clipHeight;
      /*新建一个画笔 并且开始画画*/
      const ctx = testcanvasElm.getContext('2d');
      ctx.drawImage(img, minX, minY, clipWidth, clipHeight, 0, 0, clipWidth, clipHeight);

      const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase();
      const dataURL = testcanvasElm.toDataURL('image/' + ext);


      // // 初始化这个区域
      // const clipTargetImageElm = document.createElement('img');
      // clipTargetImageElm.id = id + '';
      // clipTargetImageElm.src = testcanvasElm.toDataURL();
      // clipTargetImageElm.style.width = '200px';
      // clipTargetImageElm.style.height = '100px';
      // clipTargetImageElm.style.justifyContent = 'center';
      // clipTargetImageElm.style.objectFit = 'contain';
      // clipTargetImageElm.style.backgroundColor = '#000';
      // // 输出图片
      // this.clipTargetContainerElmRef.nativeElement.appendChild(clipTargetImageElm);

      this.targetsImageBase64.push(dataURL);

      // 画下一个目标
      this.appendClipTargetImage(targetJson, `${localStorage.getItem("targetRecognizePath")}/${this.currentDetectResult.ossKey}`, targetIdx + 1);

    };
    img.crossOrigin = 'anonymous';
    img.src = imgPath;
  }


  onFrameRecognized(videoFrame: VideoFrame): void {
    clearInterval(this.detectingInterval);

    this.videoFrameCanvasElmRef.nativeElement.setAttribute('width', videoFrame.frameWidth);
    this.videoFrameCanvasElmRef.nativeElement.setAttribute('height', videoFrame.frameHeight);
    this.videoFrameCanvasElmRef.nativeElement.style.position = 'absolute';
    this.videoFrameCanvasElmRef.nativeElement.style.left = videoFrame.x + 'px';
    this.videoFrameCanvasElmRef.nativeElement.style.bottom = videoFrame.y + 'px';

    const img = new Image();
    img.onload = () => {
      const ctx = this.videoFrameCanvasElmRef.nativeElement.getContext('2d');
      ctx.drawImage(img, 0, 0);

      ctx.strokeStyle = '#f00';

      videoFrame.detectHistory.targetJson.forEach(targetPolygon => {

        ctx.beginPath();
        ctx.moveTo(targetPolygon.x1, targetPolygon.y1);
        ctx.lineTo(targetPolygon.x2, targetPolygon.y2);
        ctx.lineTo(targetPolygon.x3, targetPolygon.y3);
        ctx.lineTo(targetPolygon.x4, targetPolygon.y4);

        ctx.closePath();
        ctx.stroke();

      });

    };

    img.src = videoFrame.dataURL;
    if (this.currentDetectResult == null || this.currentDetectResult.id !== videoFrame.detectHistory.id) {
      this.currentDetectResult = videoFrame.detectHistory;

      // this.selectedTargetPolygon = this.currentDetectResult.targetJson[0];
      this.selectTargetPolygon(this.currentDetectResult.targetJson[0]);
      this.drawTargetsPolygon(this.currentDetectResult.targetJson);
    }

  }

  // kmsSearch(historyId: string, name: string): void {
  //   const params = new HttpParams().append('historyId', historyId).append('name', name);
  //   this.http.get(`${environment.API_URL}/v1/kms/detect-kms`, {params}).subscribe((result: HttpResult<Kms[]>) => {
  //     if (HttpResult.succeed(result.code)) {
  //       this.kms = result.data;
  //       if (this.kms) {
  //         console.log('kms', this.kms);
  //         this.kmsUrl = `${environment.KMS_URL}` + this.kms[0].id;
  //       }
  //     }
  //   });
  // }

}
